<?php
/**
 * jishupu-cms
 * @Author:技术铺<jishupu@qq.com>
 * @Date: 2022/3/16
 */

namespace App\Services;

use Carbon\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Session;
use Jenssegers\Agent\Facades\Agent;

/**
 * 应用访问记录服务
 *
 * Class ViewLogService
 * @package App\Services
 */
class ViewLogService
{

    /**
     * 获取一条访问记录唯一标识
     * @param int $app_type // 平台类型：默认1网站
     * @return string
     */
    static function getUniqueId($app_type = 1): string
    {
        $request = request();
        $authId = (Auth::id() ?? 0);
        $browser = Agent::browser() ?: '';
        $browser = $browser . (Agent::version($browser) ?: '');
        $isRobot = Agent::isRobot() ? 1 : 0;
        $platform = Agent::platform() ?: '';
        $platform = $platform . (Agent::version($platform) ?: '');
        $result = $request->getUri() . $request->ip() . $app_type . $authId . Session::getId() . $browser . $isRobot . $platform;
        return md5($result);
    }

    /**
     * 添加访问记录到redis
     * 说明：通过ViewLog中间件进行应用
     * @param int $app_type
     */
    static function addViewLogRecord($app_type = 1)
    {
        $allow_view_log = ConfigService::getSiteConfig('allow_view_log');
        if ($allow_view_log) {
            $view_log_lock = RedisService::get('view_log_lock');
            if (!$view_log_lock) {
                $request = request();
                if ($request->method() == 'GET') {
                    $getUniqueId = self::getUniqueId($app_type);
                    $viewLog = [];
                    if (Redis::hExists('view_log', $getUniqueId)) {
                        $getViewLog = Redis::hGet('view_log', $getUniqueId);
                        $viewLog = json_decode($getViewLog, true);
                        $viewLog['hits'] += 1;
                    } else {
                        $viewLog['app_type'] = $app_type;
                        $viewLog['domain'] = $request->server('HTTP_HOST');
                        $viewLog['member_id'] = Auth::id() ?? 0;
                        $viewLog['session_id'] = Session::getId() ?? '';
                        $viewLog['referer'] = $request->header('Referer') ?? '';
                        $viewLog['request_uri'] = $request->getUri();
                        $viewLog['request_method'] = $request->method();
                        $requestParameters = $request->all(); // 请求参数
                        $viewLog['request_parameters'] = json_encode($requestParameters, JSON_UNESCAPED_UNICODE);
                        $viewLog['request_ip'] = $request->ip();
                        $viewLog['request_browser'] = Agent::browser() ?: '';
                        $viewLog['request_browser_version'] = Agent::version($viewLog['request_browser']) ?: '';
                        $viewLog['request_platform'] = Agent::platform() ?: '';
                        $viewLog['request_platform_version'] = Agent::version($viewLog['request_platform']) ?: '';
                        $viewLog['robot'] = Agent::isRobot() ?: 0;
                        $viewLog['hits'] = 1;
                        $viewLog['created_at'] = Carbon::now();
                    }
                    Redis::hSet('view_log', $getUniqueId, json_encode($viewLog));
                }
            }
        }
    }

    /**
     * 更新页面访问量并清除相关key
     */
    static function updateViewLogRecord()
    {
        $allow_view_log = ConfigService::getSiteConfig('allow_view_log');
        if ($allow_view_log) {
            $lock = RedisService::lock('view_log_lock');
            if ($lock->get()) {
                $viewLog = Redis::hGetAll('view_log');
                if (!empty($viewLog)) {
                    $insertFields = [
                        'app_type',
                        'domain',
                        'member_id',
                        'session_id',
                        'referer',
                        'request_uri',
                        'request_method',
                        'request_parameters',
                        'request_ip',
                        'request_browser',
                        'request_browser_version',
                        'request_platform',
                        'request_platform_version',
                        'robot',
                        'hits',
                        'created_at'
                    ];
                    $insertData = [];
                    collect($viewLog)->each(function ($item) use (&$insertData, $insertFields) {
                        $record = json_decode($item, true);
                        $oneInsert = [];
                        foreach ($insertFields as $field) {
                            $setValue = $record[$field];
                            if ($field == "created_at") {
                                $setValue = Carbon::parse($setValue);
                            }
                            $oneInsert[$field] = $setValue;
                        }
                        $insertData[] = $oneInsert;
                    });
                    DB::table('view_log')->insert($insertData);
                    Redis::del(['view_log']);
                }
                $lock->release();
            }
        }
    }

}
